import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'

// 导入自定义组件
import Fncom from './创建组件/函数组件'
import Comtest from './创建组件/类组件'
// 导入组件
// import Index from './性能优化/index'
import Index from './test'

// 使用React.createElement=》创建react元素
// const h1 = React.createElement('h1', { id: 'test' }, 'hello react-cli!')
// const z = React.createElement('span', { style: { color: 'red', display: 'block' } }, '我是span元素')
// const p = React.createElement('p', null, '我是p标签', z)
// const div1 = React.createElement('div', { className: 'div' }, h1, p, 1000, 'str')

// 使用jsx(html)创建react元素
const h1 = <div className="div">
  <h1>hello jsx!</h1>
  <p>13<span>我是span</span></p>
  <div>
    <h2>我是h2</h2>
  </div>
</div>

// 对比
let div1 = <div>我是div</div>
let div2 = React.createElement('div', null, '我是div')
console.log('虚拟DOM', div1, div2)

// 数据绑定
// - 单大括号中可以使用任意的 JavaScript 表达式 
// （值，变量，函数调用，三元运算符，数组(基本类型，jsx)）
// - **JSX 自身也是 JS 表达式** （语法糖：React.createElement()）
// - 注意：不能在{}中出现语句和对象（比如：if/for，{a:100} 等） 
let b = 'hello jsx 差值表达式！', abc = 123, obj = { a: 1, b: 3 }
let fn = () => {
  // 返回一个值=》显示到模版里边
  console.log('fn执行了')
  // return 10000
  return <span>10</span>
}
const div3 = (
  // 只能有一根
  <div className="test">
    <div>
      <h1>{b}</h1>
      <p>{1}</p>
      <ul>
        <li>{'str'}</li>
        <li>{false ? '1' : '2'}</li>
        <li>{abc}</li>
        <li>{fn()}</li>
        <li>{<b>我是b标签</b>}</li>
        <li>{[1, 2, 3]}</li>
        {/* 不支持写obj对象，但是可以写对象的键 */}
        {/* <li>{obj}</li> */}
        <li>{obj.b}</li>
      </ul>
      <p><span className="ts"></span></p>
    </div>
  </div>
)

// 条件渲染
let loaded = true // 数据是否请求成功
// 函数方式
const isLoaded = (loaded) => {
  // 条件判断
  if (loaded) {
    return (
      <div>
        <p><span>请求成功了！</span></p>
      </div>
    )
  } else {
    return (
      <div>
        <p><b>请求中...</b></p>
      </div>
    )
  }
}
const loading = (
  <div>
    {/* 三元表达式的形式 */}
    <h1>{loaded ? <span>请求成功了！</span> : <span>请求中...</span>}</h1>
    {/* 函数调用 */}
    <h2>{isLoaded(loaded)}</h2>
  </div>
)

// 列表渲染
// 假数据（从后台通过ajax调用获取的）
const songs = [
  { id: 1, name: '野狼disco', color: 'red' },
  { id: 2, name: '像我这样的人', color: 'blue' },
  { id: 3, name: '桥边姑娘', color: 'orange' }
]

// 使用map方法做列表渲染
const renderSongs = () => {
  return songs.map((item, i) => {
    return <li key={item.id}>{item.name}</li>
  })
}

// 列表渲染模版
const lists = (
  <div>
    <ul>
      {
        // 取出数组中的项放到这里渲染
        // [1, 2, 3]
        // [<li>1</li>, <li>2</li>, <li>3</li>]
        // 使用map方法做列表渲染
        songs.map((item, i) => {
          return <li className="item" style={{ backgroundColor: item.color, color: '#fff' }} key={item.id}>{item.name}</li>
        })
        // renderSongs()
      }
    </ul>
  </div>
)

// react创建组件的方式
/**
 * 1. 函数组件
 * - 函数组件：使用 JS 的函数（或箭头函数）创建的组件 
   - 函数体内要返回元素（jsx）
   - 渲染函数组件：用函数名作为**组件标签名
 * 标签名=》函数名
 */
function Fnc () {
  const b = 100
  // 返回模版
  return (
    <div>
      <h1>我是函数组件</h1>
      <p>{b}</p>
    </div>
  )
}

const Fnc2 = () => {
  return (
    <div>
      <h2>我是函数组件2</h2>
    </div>
  )
}

/**
 * 2. 使用es6 class关键字创建组件
 * - 类组件：使用 **ES6 的 class关键字** 创建的组件 
   - 类组件应该继承 React.Component 父类，从而可以使用父类中提供的方法和属性  
   - 类里边实现父类提供的render()，返回一个模版
 * 标签名=》类名  
 */
class Compt extends React.Component {
  // 模版
  render () {
    return (
      <div>
        <h1>我是类组件</h1>
        <Comtest />
      </div>
    )
  }
}

// jsx模版
const div6 = (
  <div>
    <h1>函数组件</h1>
    <Fnc />
    <Fnc2></Fnc2>
    <hr />
    <Compt />
    <hr />
    <h1>单文件组件</h1>
    <Fncom />
    <Comtest />
  </div>
)


ReactDOM.render(
  <Index />,
  document.getElementById('root')
)
